module Telco        

where

import Tipos
import SMS
import Trivia
import Gateway

data Telco = CrearTE [Gateway] | NuevoUsuario Usuario Telco |
        EnviarMensaje Usuario SMS Telco deriving (Show)

-- Funciones generales -- 

nuevoTE :: [Gateway] -> Telco
nuevoTE gs = CrearTE gs

usuariosTE :: Telco -> [Usuario]
usuariosTE (CrearTE gs) = []
usuariosTE (NuevoUsuario usuario telco) = usuario : (usuariosTE telco)
usuariosTE (EnviarMensaje usuario sms telco) = usuariosTE telco

-- Fin funciones generales -- 

-- esNroDeGatewayT -- 

esNroDeGatewayT :: Telco -> Numero -> Bool
esNroDeGatewayT telco n = estaEnGateways (dameGateways telco) n

estaEnGateways :: [Gateway] -> Int -> Bool
estaEnGateways [] n = False
estaEnGateways (gateway:xs) n = (n == numeroG gateway) || (estaEnGateways xs n)

dameGateways :: Telco -> [Gateway]
dameGateways (CrearTE gateways) = gateways
dameGateways (NuevoUsuario _ telco) = dameGateways telco
dameGateways (EnviarMensaje _ _ telco) = dameGateways telco

-- Fin esNroDeGatewayT -- 

-- gatewayTE -- 

gatewayTE :: Telco -> Numero -> Gateway
gatewayTE telco n = componerGateway (soloMensajesDeGateway telco n) n

soloMensajesDeGateway :: Telco -> Numero -> Telco
soloMensajesDeGateway (CrearTE gs) _ = CrearTE gs
soloMensajesDeGateway (NuevoUsuario u telco) n = soloMensajesDeGateway telco n
soloMensajesDeGateway (EnviarMensaje usuario sms telco) n | (nroDestinoSMS sms) == n =
        (EnviarMensaje usuario sms (soloMensajesDeGateway telco n))
                                                          | otherwise =
        soloMensajesDeGateway telco n
                                                        
componerGateway :: Telco -> Numero -> Gateway
componerGateway (CrearTE gs) n = (dameGateway gs n)
componerGateway (NuevoUsuario u telco) n = componerGateway telco n
componerGateway (EnviarMensaje u sms telco) n =
        fst (procesarSMS (componerGateway telco n) u sms) 



dameGateway :: [Gateway] -> Numero -> Gateway
dameGateway (g:gs) n | n == (numeroG g) = g
                     | otherwise = dameGateway gs n
                                                
procesarSMS :: Gateway -> Usuario -> SMS -> (Gateway,SMS)
procesarSMS gateway u sms | (elem (damePalabra (textoSMS sms)) (comandosG gateway)) =
        (procesarComandoG gateway u sms)
                          | otherwise = (procesarMensajeG gateway u sms)

-- Fin gatewayTE --        

-- mensajesTE -- 

mensajesTE :: Telco -> Usuario -> [(SMS,SMS)]
mensajesTE (CrearTE gs) _ = []
mensajesTE (NuevoUsuario _ telco) usuario = mensajesTE telco usuario
mensajesTE (EnviarMensaje usuarioT sms telco) usuario | usuario == usuarioT =
        (mensajesTE telco usuario) ++ [(sms, respuestaAlMensaje telco usuario sms)]
                                                      | otherwise =
        mensajesTE telco usuario 

respuestaAlMensaje :: Telco -> Usuario -> SMS -> SMS
respuestaAlMensaje telco usuario sms= (snd (procesarSMS
        (gatewayTE telco(nroDestinoSMS sms)) usuario sms))
                                                       
-- Fin MensajesTE -- 

-- agregarUsuarioTE -- 

agregarUsuarioTE :: Telco -> Usuario -> Telco
agregarUsuarioTE telco u = NuevoUsuario u telco

-- Fin agregarUsuarioTE -- 

-- procesarMensajeTE -- 

procesarMensajeTE :: Telco -> Usuario -> SMS -> Telco
procesarMensajeTE telco usuario sms = EnviarMensaje usuario sms telco

-- Fin procesarMensajeTE -- 

-- infoGatewaysTE -- 

infoGatewaysTE :: Telco -> [(Gateway, Int, Int)]
infoGatewaysTE telco = ordenarDescendentePorTercera (estadisticasGateways
        (componerGateways telco (dameGateways telco)))

estadisticasGateways :: [Gateway] -> [(Gateway, Int, Int)]
estadisticasGateways [] = []
estadisticasGateways (gateway:xs) = (gateway, length(triviasG gateway),
        length(usuariosG gateway)) : estadisticasGateways xs

usuariosG :: Gateway -> [Usuario]
usuariosG gateway = sacarRepetidos (usuariosDeTrivias(triviasG gateway))

usuariosDeTrivias :: [Trivia] -> [Usuario]
usuariosDeTrivias [] = []
usuariosDeTrivias (trivia:xs) = (participantesT trivia) ++ (usuariosDeTrivias xs)

componerGateways :: Telco -> [Gateway] -> [Gateway]
componerGateways _ [] = []
componerGateways telco (gateway:xs) = (gatewayTE telco (numeroG gateway)) :
        (componerGateways telco xs)

        -- Descendente por tercera -- 

ordenarDescendentePorTercera :: [(a, b, Int)] -> [(a, b, Int)]
ordenarDescendentePorTercera [x] = [x]
ordenarDescendentePorTercera (x:xs) | (esLaMayor x xs) =
        (x: ordenarDescendentePorTercera xs)
                                    | otherwise =
        ordenarDescendentePorTercera (rotar (x:xs))

rotar :: [(a, b, Int)] -> [(a, b, Int)]
rotar (x:xs) = xs ++ [x]

esLaMayor :: (a, b, Int) -> [(a, b, Int)] -> Bool
esLaMayor _ [] = True
esLaMayor x (g:gs) = ((thrd x) >= (thrd g)) && (esLaMayor x gs)

thrd :: (a, b, c) -> c
thrd (a,b,c) = c

        -- Fin descendente por tercera -- 

-- infoGTest -- 

infoGTest :: Telco -> [(Int, Int, Int)]
infoGTest telco = ordenarDescendentePorTercera (estadisticasGatewaysTest
        (componerGateways telco (dameGateways telco)))

estadisticasGatewaysTest :: [Gateway] -> [(Int, Int, Int)]
estadisticasGatewaysTest [] = []
estadisticasGatewaysTest (gateway:xs) = (numeroG gateway, length (triviasG gateway),
        length (usuariosG gateway))        : estadisticasGatewaysTest xs

-- Fin infoGTest -- 
